package com.meida.module.product.provider.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.meida.common.constants.CommonConstants;
import com.meida.common.enums.OnLineEnum;
import com.meida.common.enums.VerifyStatusEnum;
import com.meida.common.enums.YesNoEnum;
import com.meida.common.mybatis.base.service.impl.BaseServiceImpl;
import com.meida.common.mybatis.entity.EntityMap;
import com.meida.common.mybatis.model.DeleteModel;
import com.meida.common.mybatis.model.ListModel;
import com.meida.common.mybatis.model.ResultBody;
import com.meida.common.mybatis.query.CriteriaDelete;
import com.meida.common.mybatis.query.CriteriaQuery;
import com.meida.common.mybatis.query.CriteriaSave;
import com.meida.common.mybatis.query.CriteriaUpdate;
import com.meida.common.security.OpenHelper;
import com.meida.common.utils.ApiAssert;
import com.meida.common.utils.DateUtils;
import com.meida.common.utils.FlymeUtils;
import com.meida.common.utils.JsonUtils;
import com.meida.module.product.client.entity.*;
import com.meida.module.product.provider.mapper.ProdProductMapper;
import com.meida.module.product.provider.service.ProdGroupProductService;
import com.meida.module.product.provider.service.ProdProductService;
import com.meida.module.product.provider.service.ProdProductdetailsService;
import com.meida.module.product.provider.service.ProdSkuService;
import com.meida.module.system.provider.service.SysUserKeywordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/**
 * 产品 实现类
 *
 * @author flyme
 * @date 2019-07-02
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class ProdProductServiceImpl extends BaseServiceImpl<ProdProductMapper, ProdProduct> implements ProdProductService {

    @Autowired
    private ProdProductdetailsService productdetailsService;
    @Autowired
    private ProdSkuService skuService;

    @Autowired
    private ProdGroupProductService prodGroupProductService;

    @Autowired
    private SysUserKeywordService userKeywordService;

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ResultBody listEntityMap(ListModel model) {
        CriteriaQuery cq = new CriteriaQuery(model, ProdProduct.class);
        cq.select(ProdProduct.class, "productId", "productName", "productNo", "productPrice", "onLineState", "auditState", "recommend", "coverImage", "deliveryTime", "oldPrice", "saleCount");
        return baseList(cq);
    }


    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ResultBody beforePageList(CriteriaQuery<ProdProduct> cq, ProdProduct prodProduct, EntityMap requestMap) {
        //排序字段
        String order = requestMap.get("order", "createTime");
        //排序方式
        String sort = requestMap.get("sort", "desc");
        ProdProduct product = cq.getEntity(ProdProduct.class);
        List<Long> categoryIds = cq.getRequestMap().getListLong("categoryIds");
        cq.select(ProdProduct.class, "productId", "productName", "productNo", "brandName", "productPrice", "shopId", "companyId","visitCount", "productSeries", "productScore", "oldPrice", "saleCount", "onLineState", "auditState", "recommend", "createTime", "coverImage", "deliveryTime");
        cq.select(ProdCategory.class, "categoryName");
        cq.select("category2.categoryName categoryName2");
        cq.select(ProdShop.class, "shopName", "areaName");
        setCollecon(cq);
        cq.likeByField(ProdProduct.class, "productSeries");
        cq.likeByField(ProdProduct.class, "productNo");
        cq.likeByField(ProdProduct.class, "productNo");
        if (FlymeUtils.isEmpty(categoryIds)) {
            cq.eq(ProdProduct.class, "categoryId1");
            cq.eq(ProdProduct.class, "categoryId2");
        } else {
            for (int i = 0; i < categoryIds.size(); i++) {
                Integer n = i + 1;
                cq.eq(ProdProduct.class, "categoryId" + n, categoryIds.get(i));
            }
        }
        cq.likeByField(ProdProduct.class, "brandName");
        cq.eq(ProdProduct.class, "brandId");
        cq.eq(ProdProduct.class, "onLineState");
        cq.eq(ProdProduct.class, "auditState");
        cq.eq(ProdProduct.class, "place");
        if (FlymeUtils.isNotEmpty(product)) {
            if (FlymeUtils.isNotEmpty(product.getProductName())) {
                cq.and(e -> e.like(FlymeUtils.isNotEmpty(product.getProductName()), "productName", product.getProductName()).or().like(FlymeUtils.isNotEmpty(prodProduct.getProductName()), "company.companyName", product.getProductName()).or().like(FlymeUtils.isNotEmpty(prodProduct.getProductName()), "shop.shopName", product.getProductName()).or().like(FlymeUtils.isNotEmpty(prodProduct.getProductName()), "brandName", product.getProductName()).or().like(FlymeUtils.isNotEmpty(product.getProductName()), "category.categoryName", product.getProductName()).or().like(FlymeUtils.isNotEmpty(product.getProductName()), "category2.categoryName", product.getProductName()));
                userKeywordService.insert(prodProduct.getProductName());
            }
        }
        cq.createJoin(ProdCategory.class).setMainField("categoryId1");
        cq.createJoin(ProdCategory.class).setMainField("categoryId2").setJoinAlias("category2");
        cq.createJoin(ProdShop.class);
        cq.createJoin("com.meida.module.system.client.entity.SysCompany");
        cq.orderBy(order, sort);
        return ResultBody.ok();
    }


    @Override
    public ResultBody beforeEdit(CriteriaUpdate<ProdProduct> cu, ProdProduct prodProduct) {
        ProdProduct product = cu.getEntity(ProdProduct.class);
        if (FlymeUtils.isNotEmpty(product)) {
            Long productId = product.getProductId();
            EntityMap result = cu.getRequestMap();
            String productDesc = result.get("productDesc");
            String allSpec = result.get("allSpec");
            String afterService = result.get("afterService");
            String packinglist = result.get("packinglist");
            String privateSpec = result.get("privateSpec");
            ProdProductdetails prodProductdetails = Optional.ofNullable(productdetailsService.getById(productId)).orElse(new ProdProductdetails());
            prodProductdetails.setAllSpec(allSpec);
            prodProductdetails.setPackinglist(packinglist);
            prodProductdetails.setPrivateSpec(privateSpec);
            prodProductdetails.setAfterService(afterService);
            prodProductdetails.setProductDesc(productDesc);
            prodProductdetails.setProductDetailsId(productId);
            productdetailsService.saveOrUpdate(prodProductdetails);
            //保存产品所属店铺分类
            String groupIds = cu.getParams("groupIds");
            if (FlymeUtils.isNotEmpty(groupIds)) {
                prodGroupProductService.delProductGroup(productId);
                prodGroupProductService.setProductGroup(productId, groupIds.split(","));
            }
            if (FlymeUtils.isNotEmpty(product)) {
                //保存sku
                String skus = cu.getParams("skus");
                List<ProdSku> skuList = JsonUtils.toList(skus, ProdSku.class);
                if (FlymeUtils.isNotEmpty(skuList)) {
                    //清空规格
                    skuService.deleteByProductId(productId);
                    for (ProdSku prodSku : skuList) {
                        prodSku.setProductId(productId);
                        prodSku.setCompanyId(product.getCompanyId());
                        skuService.saveOrUpdate(prodSku);
                    }
                    Optional<ProdSku> min = skuList.stream().min(Comparator.comparing(ProdSku::getPrice));
                    prodProduct.setProductPrice(min.get().getPrice());
                    ProdProduct old = getById(productId);
                    prodProduct.setOldPrice(old.getProductPrice());

                }
            }
        }
        return ResultBody.ok();
    }


    @Override
    public ResultBody beforeAdd(CriteriaSave cs, ProdProduct prodProduct, EntityMap extra) {
        Long companyId = OpenHelper.getCompanyId();
        Integer onLineState = cs.getInt("onLineState", 0);
        prodProduct.setCompanyId(companyId);
        prodProduct.setShopId(companyId);
        //上架状态
        if (FlymeUtils.isNotEmpty(onLineState)) {
            prodProduct.setOnLineState(onLineState);
        } else {
            prodProduct.setOnLineState(OnLineEnum.NO.getCode());
        }
        //审批状态
        prodProduct.setAuditState(VerifyStatusEnum.NO.getCode());
        prodProduct.setVisitCount(0);
        prodProduct.setLookCount(0);
        prodProduct.setDeleted(CommonConstants.LOGIC_NOT_DELETE);
        //保存sku
        String skus = cs.getParams("skus");
        List<ProdSku> skuList = JsonUtils.toList(skus, ProdSku.class);
        cs.setExtra("skuList", skuList);
        if (FlymeUtils.isNotEmpty(skuList)) {
            Optional<ProdSku> min = skuList.stream().min(Comparator.comparing(ProdSku::getPrice));
            prodProduct.setProductPrice(min.get().getPrice());
        }
        return ResultBody.ok();
    }

    @Override
    public Boolean updateVisitCount(Long productId, Integer num) {
        CriteriaUpdate cu = new CriteriaUpdate();
        cu.setSql(true, "visitCount=visitCount+" + num);
        cu.ge("visitCount", 0);
        cu.eq(true, "productId", productId);
        return update(cu);
    }

    @Override
    public ResultBody updateLookCount(Long productId, Integer num) {
        CriteriaUpdate cu = new CriteriaUpdate();
        cu.setSql(true, "lookCount=lookCount+" + num);
        cu.ge("lookCount", 0);
        cu.eq(true, "productId", productId);
        Boolean up = update(cu);
        return ResultBody.ok();
    }

    @Override
    public ResultBody afterAdd(CriteriaSave cs, ProdProduct save, EntityMap extra) {
        Long companyId = OpenHelper.getCompanyId();
        Long productId = save.getProductId();
        String allSpec = cs.getParams("allSpec");
        String privateSpec = cs.getParams("privateSpec");
        String packinglist = cs.getParams("packinglist");
        String remark = cs.getParams("remark");
        String productDesc = cs.getParams("productDesc");
        String afterService = cs.getParams("afterService");
        ProdProductdetails details = new ProdProductdetails();
        details.setAllSpec(allSpec);
        details.setPackinglist(packinglist);
        details.setPrivateSpec(privateSpec);
        details.setAfterService(afterService);
        details.setProductDesc(productDesc);
        details.setRemark(remark);
        details.setProductDetailsId(productId);
        productdetailsService.save(details);
        //保存产品所属店铺分类
        String groupIds = cs.getParams("groupIds");
        if (FlymeUtils.isNotEmpty(groupIds)) {
            prodGroupProductService.setProductGroup(productId, groupIds.split(","));
        }
        ProdProduct product = cs.getEntity(ProdProduct.class);
        //保存sku
        List<ProdSku> skuList = cs.getExtra("skuList");
        if (FlymeUtils.isNotEmpty(product)) {
            if (FlymeUtils.isNotEmpty(skuList)) {
                for (ProdSku prodSku : skuList) {
                    prodSku.setCompanyId(companyId);
                    prodSku.setProductId(productId);
                }
                skuService.saveBatch(skuList);
            }
        }

        return ResultBody.ok("保存成功");
    }

    @Override
    public ResultBody delete(DeleteModel model) {
        CriteriaDelete cd = new CriteriaDelete(model, ProdProduct.class);
        Long[] ids = cd.getModel().getIds();

        //删除产品明细
        CriteriaDelete pd = new CriteriaDelete(model, ProdProductdetails.class);
        productdetailsService.remove(pd);
        skuService.deleteByProductId(ids);
        return baseDelete(cd);
    }

    @Override
    public ResultBody setonLineState(Long[] productIds, Integer onlineState) {
        ApiAssert.isNotEmpty("主键不能为空", productIds);
        UpdateWrapper product = new UpdateWrapper();
        product.set("onLineState", onlineState);
        product.set("onlineDate", DateUtils.getDateTime());
        product.in("productId", productIds);
        boolean result = update(product);
        if (result) {
            return ResultBody.ok(OnLineEnum.getValue(onlineState) + "成功", onlineState);
        } else {
            return ResultBody.failed(OnLineEnum.getValue(onlineState) + "失败");
        }
    }

    @Override
    public ResultBody setRecommend(Long[] productIds, Integer recommend) {
        ApiAssert.isNotEmpty("主键不能为空", productIds);
        UpdateWrapper product = new UpdateWrapper();
        product.set("recommend", recommend);
        product.in("productId", productIds);
        boolean result = update(product);
        if (result) {
            return ResultBody.ok("操作成功", recommend);
        } else {
            return ResultBody.failed("操作失败");
        }
    }

    private void setCollecon(CriteriaQuery<ProdProduct> cq) {
        //是否添加收藏标记
        Long userId = OpenHelper.getUserId();
        if (FlymeUtils.isNotEmpty(userId)) {
            cq.addSelect("(select count(targetId) from sys_collecon sc where sc.targetId=product.productId and targetEntity='ProdProduct' and userId=" + userId + ") colleconTag");
        }
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<EntityMap> listRecommend(int count, boolean collecon) {
        return listShopRecommend(null, count, collecon);
    }


    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<EntityMap> listShopRecommend(Long shopId, int count, boolean collecon) {
        CriteriaQuery cq = new CriteriaQuery(ProdProduct.class);
        cq.select(ProdProduct.class, "productId", "productName", "coverImage", "oldPrice", "saleCount", "brandName");
        cq.select(ProdShop.class, "shopName", "companyId");
        if (collecon) {
            setCollecon(cq);
        }
        cq.eq("onLineState", OnLineEnum.ON.getCode());
        cq.eq("product.recommend", YesNoEnum.YES.getCode());
        cq.eq("product.shopId", shopId);
        cq.orderByDesc("product.createTime");
        cq.createJoin(ProdShop.class);
        cq.last("limit " + count);
        return selectEntityMap(cq);
    }


    @Override
    public ResultBody setonVisibleConfig(Long[] demandIds, Integer visibleType, String visibleConfig) {
        ApiAssert.isNotEmpty("主键不能为空", demandIds);
        ApiAssert.isNotEmpty("配置不能为空", visibleConfig);
        UpdateWrapper up = new UpdateWrapper();
        up.set("visibleConfig", visibleConfig);
        up.in("productId", demandIds);
        up.set("visibleType", visibleType);
        boolean result = update(up);
        if (result) {
            return ResultBody.msg("更新成功");
        } else {
            return ResultBody.failed("更新失败");
        }
    }

    @Override
    public int totalCount(Map map, Integer onLineState) {
        CriteriaQuery cq = new CriteriaQuery(ProdProduct.class);
        if (onLineState.equals(0)) {
            cq.ne("onLineState", 1);
        } else {
            cq.eq("onLineState", 1);
        }
        return count(cq);
    }

    /**
     * 统计订单销售排名,平台按店铺分组排名，店铺按商品分组排名,按月分组
     *
     * @param params
     * @return
     */
    @Override
    public ResultBody getProductByCateGory(Map params) {
        EntityMap result = new EntityMap();
        CriteriaQuery cq = new CriteriaQuery(params, ProdProduct.class);
        cq.select("count(product.productId) prodCount");
        EntityMap totalMap = findOne(cq);
        cq.select(ProdCategory.class, "categoryName");
        cq.createJoin(ProdCategory.class).setMainField("categoryId1");
        cq.groupBy("product.categoryId1");
        List<EntityMap> list = selectEntityMap(cq);

        List<EntityMap> productList = new ArrayList<>();
        if (FlymeUtils.isNotEmpty(list)) {
            BigDecimal totalAmount = totalMap.getBigDecimal("prodCount");
            for (EntityMap entityMap : list) {
                EntityMap item = new EntityMap();
                BigDecimal amount = entityMap.getBigDecimal("prodCount");
                BigDecimal blli = amount.divide(totalAmount, 2, RoundingMode.HALF_UP);
                String categoryName = entityMap.get("categoryName");
                item.put("item", categoryName);
                item.put("count", blli);
                productList.add(item);
            }
        }
        result.put("productList", productList);
        return ResultBody.ok(result);
    }

}
